<template>
    <div class="p-vehicle-remote-detail">
        <el-form-item :label="$t('lang.maxSpeed')" prop="speed">
            <el-select v-model="maxSpeed" :placeholder="$t('lang.maxSpeed')" size="small">
                <el-option v-for="i in 100" :key="'idx' + i" :label="i" :value="i" />
            </el-select>
        </el-form-item>
        <!--speedo-->
        <div class="speedometer">
            <p class="pointer" :style="speedStyle" />
        </div>

        <el-button v-if="!running" type="success" class="el-icon-video-play" size="small" @click="handleStart">
            {{ $t('lang.start') }}
        </el-button>
        <el-button v-else type="warning" class="el-icon-video-pause" size="small" @click="handleStop">
            {{ $t('lang.stop') }}
        </el-button>

        <el-button
            :type="brakeEnabled ? 'warning' : ''"
            :class="['el-icon-remove-outline']"
            size="small"
            @pointerdown="handleBrakeDown"
            @pointerup="handleBrakeUp"
        >
            {{ $t('lang.brake') }}
        </el-button>
        <el-button
            :type="brakeEnabled ? 'warning' : ''"
            :class="['el-icon-warning-outline']"
            size="small"
            @click="handleEStop"
            v-if="eStopStatus"
        >
            {{ $t('lang.eStop') }}
        </el-button>
        <el-button
            :type="brakeEnabled ? 'warning' : ''"
            :class="['el-icon-warning-outline']"
            size="small"
            @click="handleEStop"
            v-else
        >
            {{ $t('lang.eStart') }}
        </el-button>
        <el-button
            :type="brakeEnabled ? 'warning' : ''"
            :class="['el-icon-stopwatch']"
            size="small"
            @click="handleAutosteer"
            v-if="eAutosteerStatus"
        >
            {{ $t('lang.autosteer') }}
        </el-button>
        <el-button
            :type="brakeEnabled ? 'warning' : ''"
            :class="['el-icon-stopwatch']"
            size="small"
            @click="handleAutosteer"
            v-else
        >
            {{ $t('lang.cancelsteer') }}
        </el-button>

        <!--stick-->
        <div
            class="p-stick"
            @mousedown="handlePointerDown"
            @mousemove="handlePointerMove"
            @mouseup="handlePointerUp"
            @touchstart="handlePointerDown"
            @touchmove="handlePointerMove"
            @touchend="handlePointerUp"
            @mouseleave="handlePointerLeave"
            @touchleave="handlePointerLeave"
        >
            <div class="clearance"><p ref="stick" class="stick icon icon-drag" /></div>
        </div>
    </div>
</template>

<script type="text/ecmascript-6">
// import bus from '../../vendors/eventbus.js';
import Point from '../../../utils/Point.js';
import Kernel from '../../../core/Kernel.js';
import * as Expert from '../../../utils/Expert.js';
import * as API from '../../../core/api.js';
import bus from "../../../utils/Eventbus";

export default {
    name: 'p-vehicle-remote-detail',
    components: {},
    props: {
        id: String,
        form: Object
    },
    data () {
        return {
            trueName: this.$options.name,
            running: false,
            isPointerDown: false,
            maxSpeed: 50,
            command: 0,
            speed: 0,
            steering: 0,
            dragPos: { x: 0, y: 0 },
            brakeEnabled: false,
            eStopEnabled: false,
            steerEnabled: false,
            eStopStatus: true,
            eAutosteerStatus: true
        };
    },
    computed: {
        speedStyle() {
            console.log('computed.speedStyle', this.speed);
            let style = {};
            if (this.speed < 0) {
                style.transform = 'rotate('+ (-this.speed - 50) * 0.9 + 'deg)';
            } else {
                style.transform = 'rotate('+ (this.speed - 50) * 0.9 + 'deg)';
            }
            return style;
        }
    },
    created() {
        bus.on(`${this.trueName}.stop`, this.handleStop);
    },
    mounted() {
        this.init();
    },
    beforeDestroy() {
        bus.off(`${this.trueName}.stop`, this.handleStop);
        this.stop();
        if (this.running) this.handleStop();
    },
    methods: {
        init() {
            this.stop();
            console.log('p-vehicle-remote-detail.handleStart: ');
            this.kernel = Kernel.getInstance(this.$root);
        },
        keyDownListener(keyEvent) {
            console.log('onkeydown-keyCode,code,key', keyEvent.keyCode, keyEvent.code, keyEvent.key, keyEvent);
            switch (keyEvent.keyCode) {
                case 38: //UP
                    this.speed = 100;
                    this.kernel.send({action: 'updateRemote', key: 'speed', value: this.speed});
                    keyEvent.preventDefault();
                    break;
                case 40: //DOWN
                    this.speed =-100;
                    this.kernel.send({action: 'updateRemote', key: 'speed', value: this.speed});
                    keyEvent.preventDefault();
                    break;
                case 37: //LEFT
                    this.steering = 100;
                    this.kernel.send({action: 'updateRemote', key: 'steering', value: this.steering});
                    keyEvent.preventDefault();
                    break;
                case 39: //RIGHT
                    this.steering =-100;
                    this.kernel.send({action: 'updateRemote', key: 'steering', value: this.steering});
                    keyEvent.preventDefault();
                    break;
            }
        },
        keyUpListener(keyEvent) {
            console.log('onkeyup-keyCode,code,key', keyEvent.keyCode, keyEvent.code, keyEvent.key, keyEvent);
            switch (keyEvent.keyCode) {
                case 38: //UP
                    this.speed = 0;
                    this.kernel.send({action: 'updateRemote', key: 'speed', value: this.speed});
                    keyEvent.preventDefault();
                    break;
                case 40: //DOWN
                    this.speed = 0;
                    this.kernel.send({action: 'updateRemote', key: 'speed', value: this.speed});
                    keyEvent.preventDefault();
                    break;
                case 37: //LEFT
                    this.steering = 0;
                    this.kernel.send({action: 'updateRemote', key: 'steering', value: this.steering});
                    keyEvent.preventDefault();
                    break;
                case 39: //RIGHT
                    this.steering = 0;
                    this.kernel.send({action: 'updateRemote', key: 'steering', value: this.steering});
                    keyEvent.preventDefault();
                    break;
            }
        },
        addKeyEventListener() {
            window.addEventListener('keydown', this.keyDownListener);
            window.addEventListener('keyup', this.keyUpListener);
        },
        removeKeyEventListener() {
            window.removeEventListener('keydown',this.keyDownListener);
            window.removeEventListener('keyup',this.keyUpListener);
        },
        handleStart() {
            console.log('p-vehicle-remote-detail.handleStart: ');
            this.running = true;
            API.updateVehicleRemote(this.id, true, { silent: true });
            this.animations();
            this.addKeyEventListener();
        },
        handleStop() {
            this.stop();
            this.running = false;
            if (this.isIdfind()) API.updateVehicleRemote(this.id, false, { silent: true });
            this.removeKeyEventListener();
        },
        stop() {
            if (this.timmer) cancelAnimationFrame(this.timmer);
        },
        animations() {
            if (!this.$refs.stick.parentNode.clientHeight) return;
            if (this.timmer) cancelAnimationFrame(this.timmer);
            this.$refs.stick.style.top = 50 - (this.speed / 2) + "%";
            this.$refs.stick.style.left = 50 - (this.steering / 2) + "%";


            if (Expert.checkBit(this.command, 1)) this.steerEnabled = false;
            else this.steerEnabled = true;

            if (Expert.checkBit(this.command, 2)) this.eStopEnabled = true;
            else this.eStopEnabled = false;

            if (Expert.checkBit(this.command, 3)) this.brakeEnabled = true;
            else this.brakeEnabled = false;

            // use transition to smooth out keyboard controlled movement
            let pos = this.getStickPosition();

            let yOut = Math.round(pos.y * (this.maxSpeed / 100)),
                xOut = Math.round(pos.x);

            // console.log('--------------> ', this.$refs.stick.parentNode.clientHeight, pos, pos.x === -Infinity);

            // if (yOut !== this.lastYOut) bus.emit('p-kernel.send', {action: 'updateRemote', key: 'speed', value: yOut});
            // if (xOut !== this.lastXOut) bus.emit('p-kernel.send', {action: 'updateRemote', key: 'steering', value: xOut});
            if (yOut !== this.lastYOut) this.kernel.send({action: 'updateRemote', key: 'speed', value: yOut});
            if (xOut !== this.lastXOut) this.kernel.send({action: 'updateRemote', key: 'steering', value: xOut});

            this.lastYOut = yOut;
            this.lastXOut = xOut;

            this.timmer = requestAnimationFrame(this.animations);
        },
        handleBrakeDown() {
            this.setCommandBit(3, true);
        },
        handleBrakeUp() {
            this.setCommandBit(3, false);
        },
        handleEStop() {
            this.eStopStatus = Expert.checkBit(this.command, 2);
            this.setCommandBit(2, !Expert.checkBit(this.command, 2));
        },
        handleAutosteer() {
            this.eAutosteerStatus = Expert.checkBit(this.command, 1);
            this.setCommandBit(1, !Expert.checkBit(this.command, 1));
        },
        setCommandBit(bitIndex, isOn) {
            if (Expert.checkBit(this.command, bitIndex) === isOn) return;

            if (isOn) this.command |= 1 << bitIndex;
            else this.command &= ~(1 << bitIndex);

            // bus.emit('p-kernel.send', {action: 'updateRemote', key: 'command', value: this.command});
            this.kernel.send({action: 'updateRemote', key: 'command', value: this.command});
        },
        // events
        handlePointerDown(e) {
            if (!this.running) return;
            this.isPointerDown = true;
            let sPos = this.getStickPosition(),
                pPos = this.getTrimmedPointerPosition(e);
            this.speed = sPos.y;
            this.steering = sPos.x;
            this.dragPos = new Point(sPos.x + pPos.x, sPos.y + pPos.y);
            this.$refs.stick.style.transition = 'none';

            console.log('p-vehicle-remote-detail.hanldePointerDown: ', sPos, pPos);
        },
        handlePointerMove(e) {
            if (!this.running) return;
            e.preventDefault();
            if (!this.isPointerDown) return;
            let pos = this.getTrimmedPointerPosition(e);
            this.speed = Math.min(100, Math.max(-100, this.dragPos.y - pos.y));
            this.steering = Math.min(100, Math.max(-100, this.dragPos.x - pos.x));
        },
        handlePointerUp() {
            if (!this.running) return;
            this.isPointerDown = false;
            this.speed = 0;
            this.steering = 0;
            this.$refs.stick.style.transition = 'all 1s ease-in-out';
        },
        handlePointerLeave() {
            this.isPointerDown = false;
            this.speed = 0;
            this.steering = 0;
            this.$refs.stick.style.transition = 'all 1s ease-in-out';
        },
        getStickPosition() {
            let currentStyle = window.getComputedStyle(this.$refs.stick),
                top = parseFloat(currentStyle.getPropertyValue('top')),
                left = parseFloat(currentStyle.getPropertyValue('left')),
                y = (0.5 - (top / this.$refs.stick.parentNode.clientHeight)) * 200,
                x = (0.5 - (left / this.$refs.stick.parentNode.clientWidth)) * 200;
            // console.log('--------------> ', top, left, x, y, this.$refs.stick.parentNode.clientHeight);
            return new Point(x, y);
        },
        getTrimmedPointerPosition(e) {
            let pagePos = Point.getPointerPagePos(e),
                x = 200 * pagePos.x / this.$refs.stick.parentNode.clientWidth,
                y = 200 * pagePos.y / this.$refs.stick.parentNode.clientHeight;

            return new Point(x, y);
        },
        isIdfind() {
            let row = this.$root.resources.vehicles.find(item => item.id === this.id);
            // console.error(this.$root.resources.vehicles);
            if (row) {
                return row.remoteId !== 'FREE';
            } else {
                return false;
            }
        }
    }
};
</script>

<style lang="scss">
.p-vehicle-remote-detail {
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;

    .el-button {
        margin: 8px 8px 0 0;
    }
    .speedometer {
        position: relative;
        width: 120px;
        height: 57px;
        margin: 0 50px;
        /*border: 1px solid silver;*/
        box-sizing: border-box;
        /*background-color: yellow;*/
        /*box-shadow: 0 25px 50px #daa520 inset;*/
        box-shadow: 2px 2px 5px #cccccc;
        overflow: hidden;
        background-image: url('../../../assets/images/speedometer.svg');

        .pointer {
            position: absolute;
            bottom: -30px;
            left: 0;
            right: 0;
            margin: auto;
            width: 1px;
            height: 75px;
            background-color: black;
            box-shadow: 1px 1px 10px black;
            transition: all 500ms;
            transform: rotate(-45deg);
            transform-origin: 0 100%;
        }
    }

    .p-stick {
        position: relative;
        width: 100%;
        height: 250px;
        margin-top: 5px;
        border: 1px solid silver;
        box-sizing: border-box;
        .clearance {
            position: absolute;
            top: 30px;
            left: 30px;
            bottom: 30px;
            right: 30px;
            box-sizing: border-box;
        }
        .stick {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -25px;
            margin-left: -25px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            box-shadow: 1px 1px 10px black;
            transition: all 1s ease-in-out;
            touch-action: none;
            cursor: pointer;
            text-align: center;
            line-height: 50px;
            font-size: 30px;
            /*&::before {
                content: '';
                position: absolute;
                top: 50%;
                left: 50%;
                margin-top: -26px;
                margin-left: -26px;
                width: 52px;
                height: 52px;
                background-image: url('../../assets/images/analogStick.svg');
                background-size: cover;
            }*/
        }
    }
}
</style>
